},
"registry" => {
let url = url.to_url().unwrap();
- SourceId::for_registry(&url)
+ SourceId::new(RegistryKind, url)
+ .with_precise(Some("locked".to_string()))
}
"path" => SourceId::for_path(&Path::new(url.slice_from(5))).unwrap(),
_ => fail!("Unsupported serialized SourceId")
deps: Vec<RegistryDependency>,
features: HashMap<String, Vec<String>>,
cksum: String,
+ yanked: Option<bool>,
}
#[deriving(Decodable)]
/// Parse a line from the registry's index file into a Summary for a
/// package.
- fn parse_registry_package(&mut self, line: &str) -> CargoResult<Summary> {
+ ///
+ /// The returned boolean is whether or not the summary has been yanked.
+ fn parse_registry_package(&mut self, line: &str)
+ -> CargoResult<(Summary, bool)> {
let RegistryPackage {
- name, vers, cksum, deps, features
+ name, vers, cksum, deps, features, yanked
} = try!(json::decode::<RegistryPackage>(line));
let pkgid = try!(PackageId::new(name.as_slice(),
vers.as_slice(),
}).collect();
let deps = try!(deps);
self.hashes.insert((name, vers), cksum);
- Summary::new(pkgid, deps, features)
+ Ok((try!(Summary::new(pkgid, deps, features)), yanked.unwrap_or(false)))
}
/// Converts an encoded dependency in the registry to a cargo dependency
Err(..) => return Ok(Vec::new()),
};
- let ret: CargoResult<Vec<Summary>>;
+ let ret: CargoResult<Vec<(Summary, bool)>>;
ret = contents.as_slice().lines().filter(|l| l.trim().len() > 0)
.map(|l| self.parse_registry_package(l))
.collect();
- let mut summaries = try!(ret.chain_error(|| {
+ let summaries = try!(ret.chain_error(|| {
internal(format!("Failed to parse registry's information for: {}",
dep.get_name()))
}));
+ let mut summaries = summaries.into_iter().filter(|&(_, yanked)| {
+ dep.get_source_id().get_precise().is_some() || !yanked
+ }).map(|(summary, _)| summary).collect::<Vec<_>>();
summaries.query(dep)
}
}
}
pub fn mock_pkg(name: &str, version: &str, deps: &[(&str, &str)]) {
+ mock_pkg_yank(name, version, deps, false)
+}
+
+pub fn mock_pkg_yank(name: &str, version: &str, deps: &[(&str, &str)],
+ yanked: bool) {
mock_archive(name, version, deps);
let c = File::open(&mock_archive_dst(name, version)).read_to_end().unwrap();
- let line = pkg(name, version, deps, cksum(c.as_slice()).as_slice());
+ let line = pkg(name, version, deps, cksum(c.as_slice()).as_slice(), yanked);
let file = match name.len() {
1 => format!("1/{}", name),
[&parent]).unwrap();
}
-pub fn pkg(name: &str, vers: &str, deps: &[(&str, &str)], cksum: &str) -> String {
+pub fn pkg(name: &str, vers: &str, deps: &[(&str, &str)], cksum: &str,
+ yanked: bool) -> String {
let deps = deps.iter().map(|&(a, b)| dep(a, b)).collect::<Vec<String>>();
- format!(r#"{{"name":"{}","vers":"{}","deps":{},"cksum":"{}","features":{{}}}}"#,
- name, vers, deps, cksum)
+ format!("{{\"name\":\"{}\",\"vers\":\"{}\",\
+ \"deps\":{},\"cksum\":\"{}\",\"features\":{{}},\
+ \"yanked\":{}}}",
+ name, vers, deps, cksum, yanked)
}
pub fn dep(name: &str, req: &str) -> String {
-use std::io::File;
+use std::io::{fs, File};
use support::{project, execs, cargo_dir};
use support::{UPDATING, DOWNLOADING, COMPILING, PACKAGING, VERIFYING};
{updating} registry `[..]`
", updating = UPDATING).as_slice()));
})
+
+test!(yanks_are_not_used {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ p.build();
+
+ r::mock_pkg("baz", "0.0.1", []);
+ r::mock_pkg_yank("baz", "0.0.2", [], true);
+ r::mock_pkg("bar", "0.0.1", [("baz", "*")]);
+ r::mock_pkg_yank("bar", "0.0.2", [("baz", "*")], true);
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0).with_stdout(format!("\
+{updating} registry `[..]`
+{downloading} [..] v0.0.1 (the package registry)
+{downloading} [..] v0.0.1 (the package registry)
+{compiling} baz v0.0.1 (the package registry)
+{compiling} bar v0.0.1 (the package registry)
+{compiling} foo v0.0.1 ({dir})
+", updating = UPDATING, downloading = DOWNLOADING, compiling = COMPILING,
+ dir = p.url()).as_slice()));
+})
+
+test!(relying_on_a_yank_is_bad {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ p.build();
+
+ r::mock_pkg("baz", "0.0.1", []);
+ r::mock_pkg_yank("baz", "0.0.2", [], true);
+ r::mock_pkg("bar", "0.0.1", [("baz", "=0.0.2")]);
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(101).with_stderr("\
+no package named `baz` found (required by `bar`)
+location searched: the package registry
+version required: = 0.0.2
+"));
+})
+
+test!(yanks_in_lockfiles_are_ok {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ p.build();
+
+ r::mock_pkg("bar", "0.0.1", []);
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0));
+
+ fs::rmdir_recursive(&r::registry_path().join("3")).unwrap();
+
+ r::mock_pkg_yank("bar", "0.0.1", [], true);
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0).with_stdout(format!("\
+{updating} registry `[..]`
+", updating = UPDATING).as_slice()));
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("update"),
+ execs().with_status(101).with_stderr("\
+no package named `bar` found (required by `foo`)
+location searched: the package registry
+version required: *
+"));
+})